using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace LogAnalyzer.Grabbers.Dialogs
{
    public partial class ChooseFileInFolder : Form
    {
        string _startFolder = "";
        int _currentSelIdx = -1;
        List<string> _validExtensions = new List<string>();


        public ChooseFileInFolder(string folder)
        {
            InitializeComponent();

            _startFolder = folder;
            txtFolder.Text = folder;
            DisplayFiles(LoadFiles());

            lstFiles.ListViewItemSorter = new LogFileSorter(lstFiles.Columns[0], false);

            Text = Globalization.ResourceManager.Current.GetString("CHOOSE_FILE_IN_FOLDER");
            colFileName.Text = Globalization.ResourceManager.Current.GetString("FILE_NAME");
            colModified.Text = Globalization.ResourceManager.Current.GetString("DATE_MODIFIED");
            colSize.Text = Globalization.ResourceManager.Current.GetString("ACTUAL_FILE_SIZE");
        }


        private List<LogFileInfo> LoadFiles()
        {
            _validExtensions.Add(".log");
            _validExtensions.Add(".txt");

            List<LogFileInfo> files = new List<LogFileInfo>();
            foreach (string file in Directory.GetFiles(_startFolder))
            {
                FileInfo fi = new FileInfo(file);
                if ((fi.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
                    continue;

                if (!_validExtensions.Contains(fi.Extension.ToLower()))
                    continue;


                LogFileInfo logFileInfo = new LogFileInfo();
                logFileInfo.fullPath = file;
                logFileInfo.name = fi.Name;
                logFileInfo.lastModify = fi.LastWriteTime;
                logFileInfo.size = fi.Length;
                files.Add(logFileInfo);
            }

            return files;
        }

        private void DisplayFiles(List<LogFileInfo> files)
        {
            IntPtr hImgSmall;
            IntPtr hImgLarge;

            lstFiles.LargeImageList = new ImageList();
            lstFiles.LargeImageList.ImageSize = new Size(32, 32);
            lstFiles.LargeImageList.ColorDepth = ColorDepth.Depth32Bit;

            lstFiles.SmallImageList = new ImageList();
            lstFiles.SmallImageList.ImageSize = new Size(16, 16);
            lstFiles.SmallImageList.ColorDepth = ColorDepth.Depth32Bit;

            int i = 0;
            foreach (LogFileInfo file in files)
            {
                ListViewItem itm = new ListViewItem();
                itm.Tag = file;
                itm.ImageIndex = i++;
                itm.Text = file.name;
                itm.SubItems.Add(file.lastModify.ToString("dd/MM/yyyy HH:mm"));
                itm.SubItems.Add(GetLengthString(file.size));
                lstFiles.Items.Add(itm);

                SHFILEINFO shinfoSmall = new SHFILEINFO();
                hImgSmall = SHGetFileInfo(
                    file.fullPath,
                    0,
                    ref shinfoSmall,
                    (uint)Marshal.SizeOf(shinfoSmall),
                    SHGFI_ICON | SHGFI_SMALLICON);
                Icon smallIconFile = Icon.FromHandle(shinfoSmall.hIcon);
                lstFiles.SmallImageList.Images.Add(smallIconFile);


                SHFILEINFO shinfoLarge = new SHFILEINFO();
                hImgLarge = SHGetFileInfo(
                    file.fullPath,
                    0,
                    ref shinfoLarge,
                    (uint)Marshal.SizeOf(shinfoLarge),
                    SHGFI_ICON | SHGFI_LARGEICON);
                Icon largeIconFile = Icon.FromHandle(shinfoLarge.hIcon);
                lstFiles.LargeImageList.Images.Add(largeIconFile);
            }

            lstFiles.Sort();
        }

        private string GetLengthString(long len)
        {
            float lenF = (float)len;

            if (len < 1024)
            {
                return len.ToString("#,##0") + " byte";
            }
            else if (len < (1024 * 1024))
            {
                float kb = lenF / 1024f;
                return kb.ToString("#,##0.00") + " KB";
            }
            else if (len < (1024 * 1024 * 1024))
            {
                float mb = lenF / 1024f / 1024f;
                return mb.ToString("#,##0.00") + " MB";
            }
            else
            {
                float gb = lenF / 1024f / 1024f / 1024f;
                return gb.ToString("#,##0.00") + " GB";
            }
        }


        #region Get icon

        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        }


        public const uint SHGFI_ICON = 0x100;
        public const uint SHGFI_LARGEICON = 0x0;    // 'Large icon
        public const uint SHGFI_SMALLICON = 0x1;    // 'Small icon

        [DllImport("shell32.dll")]
        public static extern IntPtr SHGetFileInfo(string pszPath,
                                    uint dwFileAttributes,
                                    ref SHFILEINFO psfi,
                                    uint cbSizeFileInfo,
                                    uint uFlags);



        #endregion


        private void lstFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstFiles.SelectedIndices.Count == 0)
                _currentSelIdx = -1;
            else
                _currentSelIdx = lstFiles.SelectedIndices[0];
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            if (_currentSelIdx == -1)
            {
                MessageBox.Show("No file selected", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            DialogResult = DialogResult.OK;
        }


        public string FileName
        {
            get
            {
                return Path.Combine(_startFolder, lstFiles.Items[_currentSelIdx].Text);
            }
        }

        private void lstFiles_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (_currentSelIdx != -1)
            {
                DialogResult = DialogResult.OK;
            }
        }

        private void lstFiles_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            LogFileSorter sorter = (LogFileSorter)lstFiles.ListViewItemSorter;
            sorter.HandleColumnHeaderClick(lstFiles.Columns[e.Column]);
            lstFiles.Sort();
            lstFiles.Sorting = SortOrder.Ascending;
        }

        #region sort arrow


        #endregion

        #region Private class

        private class LogFileSorter : IComparer
        {
            bool desc = false;
            ColumnHeader col = null;

            public LogFileSorter(ColumnHeader sortColumn, bool descendant)
            {
                desc = descendant;
                col = sortColumn;
            }

            public void HandleColumnHeaderClick(ColumnHeader column)
            {
                if (col == column)
                {
                    desc = !desc;
                }
                else
                {
                    desc = false;
                    col = column;
                }

            }

            public int Compare(object x, object y)
            {
                ListViewItem itm_x = (ListViewItem)x;
                ListViewItem itm_y = (ListViewItem)y;

                LogFileInfo lfi_x = (LogFileInfo)itm_x.Tag;
                LogFileInfo lfi_y = (LogFileInfo)itm_y.Tag;

                int res = 0;

                switch (col.Index)
                {
                    default:
                    case 0:
                        res = string.Compare(lfi_x.name.ToLower(), lfi_y.name.ToLower());
                        break;

                    case 1:
                        res = DateTime.Compare(lfi_x.lastModify, lfi_y.lastModify);
                        break;

                    case 2:
                        if (lfi_x.size > lfi_y.size)
                            res = 1;
                        else if (lfi_x.size < lfi_y.size)
                            res = -1;
                        else
                            res = 0;
                        break;
                }

                if (desc)
                    res = res * -1;

                return res;
            }

        }

        #endregion

        #region Private structures

        private struct LogFileInfo
        {
            public string fullPath;
            public string name;
            public DateTime lastModify;
            public long size;
        }

        #endregion
              
    }

}